home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / LIB / GLE / EX_RAW.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  27.9 KB  |  949 lines

  1. /*
  2.  * MODULE NAME: ex_raw.c
  3.  *
  4.  * FUNCTION: 
  5.  * This module contains code that draws extrusions with square
  6.  * ("raw join style") end styles.  It also inserts colors and normals 
  7.  * where necessary, if appropriate.
  8.  *
  9.  * HISTORY:
  10.  * written by Linas Vepstas August/September 1991
  11.  * split into multiple compile units, Linas, October 1991
  12.  * added normal vectors Linas, October 1991
  13.  * "code complete" (that is, I'm done), Linas Vepstas, October 1991
  14.  * work around OpenGL's lack of support for concave polys, June 1994
  15.  */
  16.  
  17. #include <stdlib.h>
  18. #include <math.h>
  19. #include <string.h>    /* for the memcpy() subroutine */
  20. #include <stdio.h>      /* to get stderr defined */
  21. #include <GL/tube.h>
  22.  
  23. #include "port.h"
  24. #include "gutil.h"
  25. #include "vvector.h"
  26. #include "tube_gc.h"
  27. #include "extrude.h"
  28. #include "intersect.h"
  29. #include "segment.h"
  30.  
  31. /* ============================================================ */
  32. /* 
  33.  * The following routine is, in principle, very simple:
  34.  * all that it does is normalize the up vector, and makes
  35.  * sure that it is perpendicular to the initial polyline segment.
  36.  *
  37.  * In fact, this routine gets awfully complicated because:
  38.  * a) the first few segements of the polyline might be degenerate, 
  39.  * b) up vecotr may be parallel to first few segments of polyline,
  40.  * c) etc.
  41.  *
  42.  */
  43.  
  44. void up_sanity_check (gleDouble up[3],    /* up vector for contour */
  45.                       int npoints,        /* numpoints in poly-line */
  46.                       gleDouble point_array[][3])    /* polyline */
  47. {
  48.    int i;
  49.    double len;
  50.    double diff[3];
  51.  
  52.    /* now, right off the bat, we should make sure that the up vector 
  53.     * is in fact perpendicular to the polyline direction */
  54.    VEC_DIFF (diff, point_array[1], point_array[0]);
  55.    VEC_LENGTH (len, diff);
  56.    if (len == 0.0) {
  57.       /* This error message should go through "official" error interface */
  58. /*
  59.       fprintf (stderr, "Extrusion: Warning: initial segment zero length \n");
  60. */
  61.  
  62.       /* loop till we find something that ain't of zero length */
  63.       for (i=1; i<npoints-2; i++) {
  64.          VEC_DIFF (diff, point_array[i+1], point_array[i]);
  65.          VEC_LENGTH (len, diff);
  66.          if (len != 0.0) break;
  67.       }
  68.    }
  69.  
  70.    /* normalize diff to be of unit length */
  71.    len = 1.0 / len;
  72.    VEC_SCALE (diff, len, diff);
  73.  
  74.    /* we want to take only perpendicular component of up w.r.t. the
  75.     * initial segment */
  76.    VEC_PERP (up, up, diff);
  77.  
  78.    VEC_LENGTH (len, up);
  79.    if (len == 0.0) {
  80.       /* This error message should go through "official" error interface */
  81.       fprintf (stderr, "Extrusion: Warning: ");
  82.       fprintf (stderr, "contour up vector parallel to tubing direction \n");
  83.  
  84.       /* do like the error message says ... */
  85.       VEC_COPY (up, diff);
  86.    }
  87.  
  88. }
  89.  
  90. /* ============================================================ */
  91. /* 
  92.  * This routine does what it says: It draws the end-caps for the
  93.  * "raw" join style.
  94.  */
  95.  
  96. void draw_raw_style_end_cap (int ncp,        /* number of contour points */
  97.                              gleDouble contour[][2],    /* 2D contour */
  98.                              gleDouble zval,        /* where to draw cap */
  99.                              int frontwards)    /* front or back cap */
  100. {
  101.    int j;
  102.  
  103. #ifdef OPENGL_10
  104.    GLUtriangulatorObj *tobj;
  105.    double *pts;
  106. #endif /* OPENGL_10 */
  107.  
  108.  
  109. #ifdef GL_32
  110.    /* old-style gl handles concave polygons no problem, so the code is
  111.     * simple.  New-style gl is a lot more tricky. */
  112.    point [2] = zval;
  113.    BGNPOLYGON ();
  114.       /* draw the loop counter clockwise for the front cap */
  115.       if (frontwards) {
  116.          for (j=0; j<ncp; j++) {
  117.             point [0] = contour[j][0];
  118.             point [1] = contour[j][1];
  119.             V3F (point, j, FRONT_CAP);
  120.          }
  121.  
  122.       } else {
  123.          /* the sense of the loop is reversed for backfacing culling */
  124.          for (j=ncp-1; j>-1; j--) {
  125.             point [0] = contour[j][0];
  126.             point [1] = contour[j][1];
  127.             V3F (point, j, BACK_CAP);
  128.          }
  129.       }
  130.    ENDPOLYGON ();
  131. #endif /* GL_32 */
  132.  
  133. #ifdef OPENGL_10
  134.    /* malloc the @#$%^&* array that OpenGL wants ! */
  135.    pts = (double *) malloc (3*ncp*sizeof(double));
  136.    tobj = gluNewTess ();
  137.    gluTessCallback (tobj, GLU_BEGIN, glBegin);
  138.    gluTessCallback (tobj, GLU_VERTEX, glVertex3dv);
  139.    gluTessCallback (tobj, GLU_END, glEnd);
  140.    gluBeginPolygon (tobj);
  141.  
  142.       /* draw the loop counter clockwise for the front cap */
  143.       if (frontwards) {
  144.          for (j=1; j<ncp; j++) {
  145.             pts [3*j] = contour[j][0];
  146.             pts [3*j+1] = contour[j][1];
  147.             pts [3*j+2] = zval;
  148.             gluTessVertex (tobj, &pts[3*j], &pts[3*j]);
  149.          }
  150.  
  151.       } else {
  152.          /* the sense of the loop is reversed for backfacing culling */
  153.          for (j=ncp-2; j>-1; j--) {
  154.             pts [3*j] = contour[j][0];
  155.             pts [3*j+1] = contour[j][1];
  156.             pts [3*j+2] = zval;
  157.             gluTessVertex (tobj, &pts[3*j], &pts[3*j]);
  158.          }
  159.       }
  160.  
  161.    gluEndPolygon (tobj);
  162.    free (pts);
  163.    gluDeleteTess (tobj);
  164. #endif /* OPENGL_10 */
  165. }
  166.  
  167.  
  168. /* ============================================================ */
  169. /* This routine does what it says: It draws a counter-clockwise cap 
  170.  * from a 3D contour loop list
  171.  */
  172.  
  173. void draw_front_contour_cap (int ncp,    /* number of contour points */
  174.                              gleDouble contour[][3])    /* 3D contour */
  175. {
  176.    int j;
  177. #ifdef OPENGL_10
  178.    GLUtriangulatorObj *tobj;
  179. #endif /* OPENGL_10 */
  180.  
  181. #ifdef GL_32
  182.    /* old-style gl handles concave polygons no problem, so the code is
  183.     * simple.  New-style gl is a lot more tricky. */
  184.    /* draw the end cap */
  185.    BGNPOLYGON ();
  186.  
  187.    for (j=0; j<ncp; j++) {
  188.       V3F (contour[j], j, FRONT_CAP);
  189.    }
  190.    ENDPOLYGON ();
  191. #endif /* GL_32 */
  192.  
  193. #ifdef OPENGL_10
  194.    tobj = gluNewTess ();
  195.    gluTessCallback (tobj, GLU_BEGIN, glBegin);
  196.    gluTessCallback (tobj, GLU_VERTEX, glVertex3dv);
  197.    gluTessCallback (tobj, GLU_END, glEnd);
  198.    gluBeginPolygon (tobj);
  199.  
  200.    for (j=0; j<ncp; j++) {
  201.       gluTessVertex (tobj, contour[j], contour[j]);
  202.    }
  203.    gluEndPolygon (tobj);
  204.    gluDeleteTess (tobj);
  205. #endif /* OPENGL_10 */
  206. }
  207.  
  208.  
  209. /* ============================================================ */
  210. /* This routine does what it says: It draws a clockwise cap 
  211.  * from a 3D contour loop list
  212.  */
  213.  
  214. void draw_back_contour_cap (int ncp,    /* number of contour points */
  215.                              gleDouble contour[][3])    /* 3D contour */
  216. {
  217.    int j;
  218. #ifdef OPENGL_10
  219.    GLUtriangulatorObj *tobj;
  220. #endif /* OPENGL_10 */
  221.  
  222. #ifdef GL_32
  223.    /* old-style gl handles concave polygons no problem, so the code is
  224.     * simple.  New-style gl is a lot more tricky. */
  225.  
  226.    /* draw the end cap */
  227.    /* draw the loop clockwise for the back cap */
  228.    /* the sense of the loop is reversed for backfacing culling */
  229.    BGNPOLYGON ();
  230.  
  231.    for (j=ncp-1; j>-1; j--) {
  232.       V3F (contour[j], j, BACK_CAP);
  233.    }
  234.    ENDPOLYGON ();
  235. #endif /* GL_32 */
  236.  
  237. #ifdef OPENGL_10
  238.    tobj = gluNewTess ();
  239.    gluTessCallback (tobj, GLU_BEGIN, glBegin);
  240.    gluTessCallback (tobj, GLU_VERTEX, glVertex3dv);
  241.    gluTessCallback (tobj, GLU_END, glEnd);
  242.    gluBeginPolygon (tobj);
  243.  
  244.    /* draw the end cap */
  245.    /* draw the loop clockwise for the back cap */
  246.    /* the sense of the loop is reversed for backfacing culling */
  247.    for (j=ncp-1; j>-1; j--) {
  248.       gluTessVertex (tobj, contour[j], contour[j]);
  249.    }
  250.    gluEndPolygon (tobj);
  251.    gluDeleteTess (tobj);
  252. #endif /* OPENGL_10 */
  253. }
  254.  
  255. /* ============================================================ */
  256. /* This routine draws a segment of raw-join-style tubing.
  257.  * Essentially, we assume that the proper transformations have already 
  258.  * been performed to properly orient the tube segment -- our only task
  259.  * left is to render */
  260. /* PLAIN - NO COLOR, NO NORMAL */
  261.  
  262. void draw_raw_segment_plain (int ncp,        /* number of contour points */
  263.                              gleDouble contour[][2],    /* 2D contour */
  264.                              gleDouble len,
  265.                              int inext)
  266.  
  267. {
  268.    int j;
  269.    double point[3]; 
  270.  
  271.    /* draw the tube segment */
  272.    BGNTMESH (inext, len);
  273.    for (j=0; j<ncp; j++) {
  274.       point [0] = contour[j][0];
  275.       point [1] = contour[j][1];
  276.       point [2] = 0.0;
  277.       V3F (point, j, FRONT);
  278.  
  279.       point [2] = - len;
  280.       V3F (point, j, BACK);
  281.    }
  282.  
  283.    if (__TUBE_CLOSE_CONTOUR) {
  284.       /* connect back up to first point of contour */
  285.       point [0] = contour[0][0];
  286.       point [1] = contour[0][1];
  287.       point [2] = 0.0;
  288.       V3F (point, 0, FRONT);
  289.    
  290.       point [2] = - len;
  291.       V3F (point, 0, BACK);
  292.    }
  293.  
  294.    ENDTMESH ();
  295.  
  296.    /* draw the endcaps, if the join style calls for it */
  297.    if (__TUBE_DRAW_CAP) {
  298.  
  299.       /* draw the front cap */
  300.       draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
  301.  
  302.       /* draw the back cap */
  303.       draw_raw_style_end_cap (ncp, contour, -len, FALSE);
  304.    }
  305.  
  306. }
  307.  
  308. /* ============================================================ */
  309. /* This routine draws a segment of raw-join-style tubing.
  310.  * Essentially, we assume that the proper transformations have already 
  311.  * been performed to properly orient the tube segment -- our only task
  312.  * left is to render */
  313. /* COLOR -- DRAW ONLY COLOR */
  314.  
  315. void draw_raw_segment_color (int ncp,        /* number of contour points */
  316.                              gleDouble contour[][2],    /* 2D contour */
  317.                              float color_array[][3],    /* color of polyline */
  318.                              gleDouble len,
  319.                              int inext)
  320.  
  321. {
  322.    int j;
  323.    double point[3]; 
  324.  
  325.    /* draw the tube segment */
  326.    BGNTMESH (inext, len);
  327.    for (j=0; j<ncp; j++) {
  328.       point [0] = contour[j][0];
  329.       point [1] = contour[j][1];
  330.       point [2] = 0.0;
  331.       C3F (color_array[inext-1]);
  332.       V3F (point, j, FRONT);
  333.  
  334.       point [2] = - len;
  335.       C3F (color_array[inext]);    
  336.       V3F (point, j, BACK);
  337.    }
  338.  
  339.    if (__TUBE_CLOSE_CONTOUR) {
  340.       /* connect back up to first point of contour */
  341.       point [0] = contour[0][0];
  342.       point [1] = contour[0][1];
  343.       point [2] = 0.0;
  344.    
  345.       C3F (color_array[inext-1]);
  346.       V3F (point, 0, FRONT);
  347.    
  348.       point [2] = - len;
  349.       C3F (color_array[inext]);    
  350.       V3F (point, 0, BACK);
  351.    }
  352.  
  353.    ENDTMESH ();
  354.  
  355.    /* draw the endcaps, if the join style calls for it */
  356.    if (__TUBE_DRAW_CAP) {
  357.  
  358.       /* draw the front cap */
  359.       C3F (color_array[inext-1]);    
  360.       draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
  361.  
  362.       /* draw the back cap */
  363.       C3F (color_array[inext]);    
  364.       draw_raw_style_end_cap (ncp, contour, -len, FALSE);
  365.    }
  366.  
  367. }
  368.  
  369. /* ============================================================ */
  370. /* This routine draws a segment of raw-join-style tubing.
  371.  * Essentially, we assume that the proper transformations have already 
  372.  * been performed to properly orient the tube segment -- our only task
  373.  * left is to render */
  374. /* EDGE_N -- DRAW ONLY EDGE NORMALS */
  375.  
  376. void draw_raw_segment_edge_n (int ncp,    /* number of contour points */
  377.                              gleDouble contour[][2],    /* 2D contour */
  378.                              gleDouble cont_normal[][2],/* 2D normal vecs */
  379.                              gleDouble len,
  380.                              int inext)
  381.  
  382. {
  383.    int j;
  384.    double point[3]; 
  385.    double norm[3]; 
  386.  
  387.    /* draw the tube segment */
  388.    norm [2] = 0.0;
  389.    BGNTMESH (inext, len);
  390.    for (j=0; j<ncp; j++) {
  391.       norm [0] = cont_normal[j][0];
  392.       norm [1] = cont_normal[j][1];
  393.       N3F (norm);
  394.  
  395.       point [0] = contour[j][0];
  396.       point [1] = contour[j][1];
  397.       point [2] = 0.0;
  398.       V3F (point, j, FRONT);
  399.  
  400.       point [2] = - len;
  401.       V3F (point, j, BACK);
  402.    }
  403.  
  404.    if (__TUBE_CLOSE_CONTOUR) {
  405.       /* connect back up to first point of contour */
  406.       norm [0] = cont_normal[0][0];
  407.       norm [1] = cont_normal[0][1];
  408.       norm [2] = 0.0;
  409.       N3F (norm);
  410.    
  411.       point [0] = contour[0][0];
  412.       point [1] = contour[0][1];
  413.       point [2] = 0.0;
  414.       V3F (point, 0, FRONT);
  415.    
  416.       point [2] = - len;
  417.       V3F (point, 0, BACK);
  418.    }
  419.  
  420.    ENDTMESH ();
  421.  
  422.    /* draw the endcaps, if the join style calls for it */
  423.    if (__TUBE_DRAW_CAP) {
  424.  
  425.       /* draw the front cap */
  426.       norm [0] = norm [1] = 0.0;
  427.       norm [2] = 1.0;
  428.       N3F (norm);
  429.       draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
  430.  
  431.       /* draw the back cap */
  432.       norm [2] = -1.0;
  433.       N3F (norm);
  434.       draw_raw_style_end_cap (ncp, contour, -len, FALSE);
  435.    }
  436.  
  437. }
  438.  
  439. /* ============================================================ */
  440. /* This routine draws a segment of raw-join-style tubing.
  441.  * Essentially, we assume that the proper transformations have already 
  442.  * been performed to properly orient the tube segment -- our only task
  443.  * left is to render */
  444. /* C_AND_EDGE_N -- DRAW EDGE NORMALS AND COLORS */
  445.  
  446. void draw_raw_segment_c_and_edge_n (int ncp,    /* number of contour points */
  447.                              gleDouble contour[][2],    /* 2D contour */
  448.                              float color_array[][3],    /* color of polyline */
  449.                              gleDouble cont_normal[][2],/* 2D normal vecs */
  450.                              gleDouble len,
  451.                              int inext)
  452.  
  453. {
  454.    int j;
  455.    double point[3]; 
  456.    double norm[3];
  457.  
  458.    /* draw the tube segment */
  459.    norm [2] = 0.0;
  460.    BGNTMESH (inext, len);
  461.    for (j=0; j<ncp; j++) {
  462.       C3F (color_array[inext-1]);
  463.  
  464.       norm [0] = cont_normal[j][0];
  465.       norm [1] = cont_normal[j][1];
  466.       N3F (norm);
  467.  
  468.       point [0] = contour[j][0];
  469.       point [1] = contour[j][1];
  470.       point [2] = 0.0;
  471.       V3F (point, j, FRONT);
  472.  
  473.       C3F (color_array[inext]);    
  474.       N3F (norm);
  475.  
  476.       point [2] = - len;
  477.       V3F (point, j, BACK);
  478.    }
  479.  
  480.    if (__TUBE_CLOSE_CONTOUR) {
  481.       /* connect back up to first point of contour */
  482.       C3F (color_array[inext-1]);
  483.    
  484.       norm [0] = cont_normal[0][0];
  485.       norm [1] = cont_normal[0][1];
  486.       N3F (norm);
  487.    
  488.       point [0] = contour[0][0];
  489.       point [1] = contour[0][1];
  490.       point [2] = 0.0;
  491.       V3F (point, 0, FRONT);
  492.       
  493.    
  494.       C3F (color_array[inext]);    
  495.       norm [0] = cont_normal[0][0];
  496.       norm [1] = cont_normal[0][1];
  497.       N3F (norm);
  498.    
  499.       point [2] = - len;
  500.       V3F (point, 0, BACK);
  501.    }
  502.  
  503.    ENDTMESH ();
  504.  
  505.    /* draw the endcaps, if the join style calls for it */
  506.    if (__TUBE_DRAW_CAP) {
  507.  
  508.       /* draw the front cap */
  509.       C3F (color_array[inext-1]);    
  510.       norm [0] = norm [1] = 0.0;
  511.       norm [2] = 1.0;
  512.       N3F (norm);
  513.       draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
  514.  
  515.       /* draw the back cap */
  516.       C3F (color_array[inext]);    
  517.       norm [2] = -1.0;
  518.       N3F (norm);
  519.       draw_raw_style_end_cap (ncp, contour, -len, FALSE);
  520.    }
  521.  
  522. }
  523.  
  524. /* ============================================================ */
  525. /* This routine draws a segment of raw-join-style tubing.
  526.  * Essentially, we assume that the proper transformations have already 
  527.  * been performed to properly orient the tube segment -- our only task
  528.  * left is to render */
  529. /* FACET_N -- DRAW ONLY FACET NORMALS */
  530.  
  531. void draw_raw_segment_facet_n (int ncp,    /* number of contour points */
  532.                              gleDouble contour[][2],    /* 2D contour */
  533.                              gleDouble cont_normal[][2],/* 2D normal vecs */
  534.                              gleDouble len,
  535.                              int inext)
  536.  
  537. {
  538.    int j;
  539.    double point[3]; 
  540.    double norm[3]; 
  541.  
  542.    /* draw the tube segment */
  543.    norm [2] = 0.0;
  544.    BGNTMESH (inext, len);
  545.    for (j=0; j<ncp-1; j++) {
  546.       /* facet normals require one normal per four vertices */
  547.       norm [0] = cont_normal[j][0];
  548.       norm [1] = cont_normal[j][1];
  549.       N3F (norm);
  550.  
  551.       point [0] = contour[j][0];
  552.       point [1] = contour[j][1];
  553.       point [2] = 0.0;
  554.       V3F (point, j, FRONT);
  555.  
  556.       point [2] = - len;
  557.       V3F (point, j, BACK);
  558.  
  559.       point [0] = contour[j+1][0];
  560.       point [1] = contour[j+1][1];
  561.       point [2] = 0.0;
  562.       V3F (point, j+1, FRONT);
  563.  
  564.       point [2] = - len;
  565.       V3F (point, j+1, BACK);
  566.    }
  567.  
  568.    if (__TUBE_CLOSE_CONTOUR) {
  569.       /* connect back up to first point of contour */
  570.       norm [0] = cont_normal[ncp-1][0];
  571.       norm [1] = cont_normal[ncp-1][1];
  572.       N3F (norm);
  573.    
  574.       point [0] = contour[ncp-1][0];
  575.       point [1] = contour[ncp-1][1];
  576.       point [2] = 0.0;
  577.       V3F (point, ncp-1, FRONT);
  578.    
  579.       point [2] = - len;
  580.       V3F (point, ncp-1, BACK);
  581.    
  582.       point [0] = contour[0][0];
  583.       point [1] = contour[0][1];
  584.       point [2] = 0.0;
  585.       V3F (point, 0, FRONT);
  586.    
  587.       point [2] = - len;
  588.       V3F (point, 0, BACK);
  589.    }
  590.  
  591.    ENDTMESH ();
  592.  
  593.    /* draw the endcaps, if the join style calls for it */
  594.    if (__TUBE_DRAW_CAP) {
  595.  
  596.       /* draw the front cap */
  597.       norm [0] = norm [1] = 0.0;
  598.       norm [2] = 1.0;
  599.       N3F (norm);
  600.       draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
  601.  
  602.       /* draw the back cap */
  603.       norm [2] = -1.0;
  604.       N3F (norm);
  605.       draw_raw_style_end_cap (ncp, contour, -len, FALSE);
  606.    }
  607.  
  608. }
  609.  
  610. /* ============================================================ */
  611. /* This routine draws a segment of raw-join-style tubing.
  612.  * Essentially, we assume that the proper transformations have already 
  613.  * been performed to properly orient the tube segment -- our only task
  614.  * left is to render */
  615. /* C_AND_FACET_N -- DRAW FACET NORMALS AND COLORS */
  616.  
  617. void draw_raw_segment_c_and_facet_n (int ncp,    /* number of contour points */
  618.                              gleDouble contour[][2],    /* 2D contour */
  619.                              float color_array[][3],    /* color of polyline */
  620.                              gleDouble cont_normal[][2],/* 2D normal vecs */
  621.                              gleDouble len,
  622.                              int inext)
  623.  
  624. {
  625.    int j;
  626.    double point[3]; 
  627.    double norm[3]; 
  628.  
  629.    /* draw the tube segment */
  630.    norm [2] = 0.0;
  631.    BGNTMESH (inext, len);
  632.    for (j=0; j<ncp-1; j++) {
  633.       /* facet normals require one normal per four vertices;
  634.        * However, we have to respecify normal each time at each vertex 
  635.        * so that the lighting equation gets triggered.  (V3F does NOT
  636.        * automatically trigger the lighting equations -- it only
  637.        * triggers when there is a local light) */
  638.  
  639.       C3F (color_array[inext-1]);
  640.  
  641.       norm [0] = cont_normal[j][0];
  642.       norm [1] = cont_normal[j][1];
  643.       N3F (norm);
  644.  
  645.       point [0] = contour[j][0];
  646.       point [1] = contour[j][1];
  647.       point [2] = 0.0;
  648.       V3F (point, j, FRONT);
  649.  
  650.       C3F (color_array[inext]);    
  651.       N3F (norm);
  652.       point [2] = - len;
  653.       V3F (point, j, BACK);
  654.       
  655.  
  656.       C3F (color_array[inext-1]);
  657.       N3F (norm);
  658.  
  659.       point [0] = contour[j+1][0];
  660.       point [1] = contour[j+1][1];
  661.       point [2] = 0.0;
  662.       V3F (point, j+1, FRONT);
  663.  
  664.       C3F (color_array[inext]);    
  665.       N3F (norm);
  666.       point [2] = - len;
  667.       V3F (point, j+1, BACK);
  668.    }
  669.  
  670.    if (__TUBE_CLOSE_CONTOUR) {
  671.       /* connect back up to first point of contour */
  672.       point [0] = contour[ncp-1][0];
  673.       point [1] = contour[ncp-1][1];
  674.       point [2] = 0.0;
  675.       C3F (color_array[inext-1]);
  676.    
  677.       norm [0] = cont_normal[ncp-1][0];
  678.       norm [1] = cont_normal[ncp-1][1];
  679.       N3F (norm);
  680.       V3F (point, ncp-1, FRONT);
  681.    
  682.       C3F (color_array[inext]);    
  683.       N3F (norm);
  684.    
  685.       point [2] = - len;
  686.       V3F (point, ncp-1, BACK);
  687.    
  688.       C3F (color_array[inext-1]);
  689.    
  690.       norm [0] = cont_normal[0][0];
  691.       norm [1] = cont_normal[0][1];
  692.       N3F (norm);
  693.    
  694.       point [0] = contour[0][0];
  695.       point [1] = contour[0][1];
  696.       point [2] = 0.0;
  697.       V3F (point, 0, FRONT);
  698.    
  699.       C3F (color_array[inext]);    
  700.       N3F (norm);
  701.    
  702.       point [2] = - len;
  703.       V3F (point, 0, BACK);
  704.    }
  705.    
  706.    ENDTMESH ();
  707.  
  708.    /* draw the endcaps, if the join style calls for it */
  709.    if (__TUBE_DRAW_CAP) {
  710.  
  711.       /* draw the front cap */
  712.       C3F (color_array[inext-1]);    
  713.       norm [0] = norm [1] = 0.0;
  714.       norm [2] = 1.0;
  715.       N3F (norm);
  716.       draw_raw_style_end_cap (ncp, contour, 0.0, TRUE);
  717.  
  718.       /* draw the back cap */
  719.       C3F (color_array[inext]);    
  720.       norm [2] = -1.0;
  721.       N3F (norm);
  722.       draw_raw_style_end_cap (ncp, contour, -len, FALSE);
  723.    }
  724.  
  725. }
  726.  
  727. /* ============================================================ */
  728. /* This routine draws "raw" style extrusions.  By "raw" style, it is
  729.  * meant extrusions with square ends: ends that are cut at 90 degrees to
  730.  * the length of the extrusion.  End caps are NOT drawn, unless the end cap
  731.  * style is indicated.
  732.  */
  733.  
  734. void extrusion_raw_join (int ncp,        /* number of contour points */
  735.                          gleDouble contour[][2],    /* 2D contour */
  736.                          gleDouble cont_normal[][2],/* 2D contour normal vecs */
  737.                          gleDouble up[3],    /* up vector for contour */
  738.                          int npoints,        /* numpoints in poly-line */
  739.                          gleDouble point_array[][3],    /* polyline */
  740.                          float color_array[][3],    /* color of polyline */
  741.                          gleDouble xform_array[][2][3])   /* 2D contour xforms */
  742. {
  743.    int i, j;
  744.    int inext;
  745.    gleDouble m[4][4];
  746.    gleDouble len;
  747.    gleDouble diff[3];
  748.    gleDouble bi_0[3];        /* bisecting plane */
  749.    gleDouble yup[3];        /* alternate up vector */
  750.    gleDouble nrmv[3];
  751.    short no_norm, no_cols, no_xform;     /*booleans */
  752.    char *mem_anchor;
  753.    gleDouble *front_loop, *back_loop;  /* countour loops */
  754.    gleDouble *front_norm, *back_norm;  /* countour loops */
  755.    gleDouble *tmp;
  756.    
  757.    nrmv[0] = nrmv[1] = 0.0;   /* used for drawing end caps */
  758.    /* use some local variables for needed booleans */
  759.    no_norm = (cont_normal == NULL);
  760.    no_cols = (color_array == NULL);
  761.    no_xform = (xform_array == NULL);
  762.  
  763.    /* alloc loop arrays if needed */
  764.    if (! no_xform) {
  765.       mem_anchor = malloc (4 * ncp * 3 * sizeof(gleDouble));
  766.       front_loop = (gleDouble *) mem_anchor;
  767.       back_loop = front_loop + 3*ncp;
  768.       front_norm = back_loop + 3*ncp;
  769.       back_norm = front_norm + 3*ncp;
  770.    }
  771.  
  772.    /* By definition, the contour passed in has its up vector pointing in
  773.     * the y direction */
  774.    if (up == NULL) {
  775.       yup[0] = 0.0;
  776.       yup[1] = 1.0;
  777.       yup[2] = 0.0;
  778.    } else {
  779.       VEC_COPY (yup, up);
  780.    }
  781.  
  782.    /* ========== "up" vector sanity check ========== */
  783.    (void) up_sanity_check (yup, npoints, point_array);
  784.  
  785.    /* ignore all segments of zero length */
  786.    i = 1;
  787.    inext = i;
  788.    FIND_NON_DEGENERATE_POINT (inext, npoints, len, diff, point_array);
  789.  
  790.    /* first time through, get the loops */
  791.    if (! no_xform) {
  792.       for (j=0; j<ncp; j++) {
  793.             MAT_DOT_VEC_2X3 ((&front_loop[3*j]), 
  794.                              xform_array[inext-1], contour[j]);
  795.             front_loop[3*j+2] = 0.0;
  796.       }
  797.       if (!no_norm) {
  798.          for (j=0; j<ncp; j++) {
  799.             NORM_XFORM_2X2 ( (&front_norm[3*j]),
  800.                              xform_array[inext-1],
  801.                              cont_normal [j]);
  802.             front_norm[3*j+2] = 0.0;
  803.             back_norm[3*j+2] = 0.0;
  804.          }
  805.       }
  806.    }
  807.  
  808.    /* draw tubing, not doing the first segment */
  809.    while (inext<npoints-1) {
  810.  
  811.       /* get the two bisecting planes */
  812.       bisecting_plane (bi_0, point_array[i-1], 
  813.                              point_array[i], 
  814.                              point_array[inext]);
  815.  
  816.       /* reflect the up vector in the bisecting plane */
  817.       VEC_REFLECT (yup, yup, bi_0);
  818.  
  819.       /* rotate so that z-axis points down v2-v1 axis, 
  820.        * and so that origen is at v1 */
  821.       uviewpoint (m, point_array[i], point_array[inext], yup);
  822.       PUSHMATRIX ();
  823.       MULTMATRIX (m);
  824.  
  825.       /* There are six different cases we can have for presence and/or
  826.        * absecnce of colors and normals, and for interpretation of
  827.        * normals. The blechy set of nested if statements below
  828.        * branch to each of the six cases */
  829.       if (no_xform) {
  830.          if (no_cols) {
  831.             if (no_norm) {
  832.                draw_raw_segment_plain (ncp, contour, len, inext);
  833.             } else 
  834.             if (__TUBE_DRAW_FACET_NORMALS) {
  835.                draw_raw_segment_facet_n (ncp, contour, cont_normal,
  836.                                                len, inext);
  837.             } else {
  838.                draw_raw_segment_edge_n (ncp, contour, cont_normal,
  839.                                                len, inext);
  840.             }
  841.          } else {
  842.             if (no_norm) {
  843.                draw_raw_segment_color (ncp, contour, color_array, len, inext);
  844.             } else 
  845.             if (__TUBE_DRAW_FACET_NORMALS) {
  846.                draw_raw_segment_c_and_facet_n (ncp, contour, 
  847.                                                color_array,
  848.                                                cont_normal,
  849.                                                len, inext);
  850.             } else {
  851.                draw_raw_segment_c_and_edge_n (ncp, contour, 
  852.                                               color_array,
  853.                                               cont_normal,
  854.                                               len, inext);
  855.              }
  856.           }
  857.       } else {
  858.  
  859.          /* else -- there are scales and offsets to deal with */
  860.          for (j=0; j<ncp; j++) {
  861.             MAT_DOT_VEC_2X3 ((&back_loop[3*j]), 
  862.                              xform_array[inext], contour[j]);
  863.             back_loop[3*j+2] = -len;
  864.             front_loop[3*j+2] = 0.0;
  865.          }
  866.  
  867.          if (!no_norm) {
  868.             for (j=0; j<ncp; j++) {
  869.                NORM_XFORM_2X2 ( (&back_norm[3*j]),
  870.                                              xform_array[inext],
  871.                                              cont_normal [j]);
  872.             }
  873.          }
  874.  
  875.          if (no_cols) {
  876.             if (no_norm) {
  877.                draw_segment_plain (ncp,
  878.              (gleDouble (*)[3]) front_loop, (gleDouble (*)[3]) back_loop, inext, len);
  879.             } else
  880.             if (__TUBE_DRAW_FACET_NORMALS) {
  881.                draw_binorm_segment_facet_n (ncp, (gleDouble (*)[3]) front_loop, (gleDouble (*)[3]) back_loop, 
  882.                                                  (gleDouble (*)[3]) front_norm, (gleDouble (*)[3]) back_norm, inext, len);
  883.             } else {
  884.                draw_binorm_segment_edge_n (ncp, (gleDouble (*)[3]) front_loop, (gleDouble (*)[3]) back_loop, 
  885.                                                 (gleDouble (*)[3]) front_norm, (gleDouble (*)[3]) back_norm, inext, len);
  886.             }
  887.             if (__TUBE_DRAW_CAP) {
  888.                 nrmv[2] = 1.0; N3F (nrmv);
  889.                 draw_front_contour_cap (ncp, (gleVector *) front_loop);
  890.                 nrmv[2] = -1.0; N3F (nrmv);
  891.                 draw_back_contour_cap (ncp, (gleVector *) back_loop);
  892.             }
  893.          } else {
  894.             if (no_norm) {
  895.                draw_segment_color (ncp, (gleDouble (*)[3]) front_loop, (gleDouble (*)[3]) back_loop,
  896.                                    color_array[inext-1],
  897.                                    color_array[inext], inext, len);
  898.             } else
  899.             if (__TUBE_DRAW_FACET_NORMALS) {
  900.                draw_binorm_segment_c_and_facet_n (ncp,
  901.                                    (gleDouble (*)[3]) front_loop, (gleDouble (*)[3]) back_loop,
  902.                                    (gleDouble (*)[3]) front_norm, (gleDouble (*)[3]) back_norm,
  903.                                    color_array[inext-1],
  904.                                    color_array[inext], inext, len);
  905.             } else {
  906.                draw_binorm_segment_c_and_edge_n (ncp,
  907.                                    (gleDouble (*)[3]) front_loop, (gleDouble (*)[3]) back_loop,
  908.                                    (gleDouble (*)[3]) front_norm, (gleDouble (*)[3]) back_norm,
  909.                                    color_array[inext-1],
  910.                                    color_array[inext],
  911.                    len, inext);
  912.             }
  913.             if (__TUBE_DRAW_CAP) {
  914.                 C3F (color_array[inext-1]);
  915.                 nrmv[2] = 1.0; N3F (nrmv);
  916.                 draw_front_contour_cap (ncp, (gleVector *) front_loop);
  917.  
  918.                 C3F (color_array[inext]);
  919.                 nrmv[2] = -1.0; N3F (nrmv);
  920.                 draw_back_contour_cap (ncp, (gleVector *) back_loop);
  921.             }
  922.          }
  923.       }
  924.  
  925.       /* pop this matrix, do the next set */
  926.       POPMATRIX ();
  927.  
  928.       /* flop over transformed loops */
  929.       tmp = front_loop;
  930.       front_loop = back_loop;
  931.       back_loop = tmp;
  932.       tmp = front_norm;
  933.       front_norm = back_norm;
  934.       back_norm = tmp;
  935.  
  936.       i = inext;
  937.       /* ignore all segments of zero length */
  938.       FIND_NON_DEGENERATE_POINT (inext, npoints, len, diff, point_array);
  939.  
  940.    }
  941.  
  942.    /* free previously allocated memory, if any */
  943.    if (!no_xform) {
  944.       free (mem_anchor);
  945.    }
  946. }
  947.    
  948. /* ============================================================ */
  949.